#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <map>
#include <functional>
#include <atomic>
#include <thread>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <vector>
#include "TcpProtocol.h"

namespace BORNS {

class TcpServer
{
public:
    TcpServer(uint16_t port,
              TcpProtocol::Type p = TcpProtocol::Type::Default);
    ~TcpServer();
    /*!
   * \brief Reads data from the socket(没有拆包功能)
   *
   * \param[in] 需要读取的客户端套接字
   * \param[out] buf Buffer where the data shall be stored
   * \param[in] buf_len Number of bytes allocated for the buffer
   * \param[out] read Number of bytes actually read
   *
   * \returns True on success, false otherwise
   */
    bool Read(int sock, uint8_t *buf, const size_t buf_len, size_t& read);
    /*!
   * \brief Reads data from the socket
   *
   * \param[in] 需要读取的客户端设备种类(没有拆包功能)
   * \param[out] buf Buffer where the data shall be stored
   * \param[in] buf_len Number of bytes allocated for the buffer
   * \param[out] read Number of bytes actually read
   *
   * \returns True on success, false otherwise
   */
    bool Read(const TcpProtocol::Device &dev, uint8_t *buf, const size_t buf_len, size_t& read);
    /*!
   * \brief Writes to the socket
   *
   * \param[in] 需要发送的客户端套接字
   * \param[in] buf Buffer of bytes to write
   * \param[in] buf_len Number of bytes in the buffer
   *
   * \returns True on success, false otherwise
   */
    bool Write(int sock, const uint8_t *buf, size_t buf_len);
    bool Write(int sock, const std::vector<uint8_t> &buf);
    /*!
   * \brief Writes to the socket
   *
   * \param[in] 需要发送的客户端套接字
   * \param[in] buf Buffer of bytes to write
   *
   * \returns True on success, false otherwise
   */
    bool Write(int sock, void *buf, size_t buf_len);
    /*!
   * \brief Writes to the socket
   *
   * \param[in] 需要发送的客户端设备种类
   * \param[in] buf Buffer of bytes to write
   * \param[in] buf_len Number of bytes in the buffer
   *
   * \returns True on success, false otherwise
   */
    bool Write(const TcpProtocol::Device &dev, const uint8_t *buf, size_t buf_len);
    bool Write(const TcpProtocol::Device &dev, const std::vector<uint8_t> &buf);
    /*!
   * \brief Writes to the socket
   *
   * \param[in] 需要发送的客户端设备种类
   * \param[in] buf Buffer of bytes to write
   *
   * \returns True on success, false otherwise
   */
    bool Write(const TcpProtocol::Device &dev, void *buf, size_t buf_len);
    /*!
   * \brief 向所有已连接的客户端发送数据
   *
   * \param[in] buf Buffer of bytes to write
   * \param[in] buf_len Number of bytes in the buffer
   *
   * \returns True on success, false otherwise
   */
    bool WriteAll(const uint8_t *buf, size_t buf_len);
    bool WriteAll(const std::vector<uint8_t> &buf);
    /*!
   * \brief 向所有已连接的客户端发送数据
   *
   * \param[in] buf Buffer of bytes to write
   *
   * \returns True on success, false otherwise
   */
    bool WriteAll(const void *buf, size_t buf_len);
    /*!
   * \brief 注册接收数据回调函数（不接收数据可不调用该接口）
   * \brief 非TcpProtocol::Type::HeaderData协议：调用者必须负责删除已解析的数据缓存
   *
   * \param[in] 本次数据包的sockid
   * \param[in] 待解析的数据包
   */
    void SetRcvFunc(std::function<void(std::vector<uint8_t> &bytes, const TcpProtocol::Device &dev)> f);
private:
    void AcceptThread();
    void RcvThread(int sockId);
    /*!从
   * \brief 拆包：取前4个byte->int packageSize 根据packageSize拆包
   *
   * \param[in] 客户端sockid
   * \param[in] 解析的buffer
   * \param[in] 是否为首次解析
   */
    void Unpack(int sockId, std::vector<uint8_t> &bytes, bool &isFirst);
    /*!
   * \brief 最底层的发送数据接口，未作任何数据包装处理
   *
   * \param[in] 发送的客户端id
   * \param[in] buf Buffer of bytes to write
   * \param[in] buf_len Number of bytes in the buffer
   * \param[out] written Number of bytes actually written
   *
   * \returns True on success, false otherwise
   */
    bool Write(int sock, const uint8_t *buf, const size_t buf_len, size_t& written);
private:
    std::thread *acceptThread_;
    std::atomic_bool running_;
    int sockListen_;// 监听套接字
    std::map<TcpProtocol::Device, int> clients_;// 连接上的客户端映射表
    std::function<void(std::vector<uint8_t> &bytes, const TcpProtocol::Device &dev)> parseFunc_;//
    TcpProtocol::Type proType_;// 协议种类
};

}// namespace BORNS

#endif // TCPSERVER_H
